home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / docs / misc / ConcNews.lha / news / amiga.programming / comp.sys.amiga.programmer_10351_000067.msg < prev    next >
Encoding:
Internet Message Format  |  1994-11-27  |  7.8 KB

  1. Path: dd.chalmers.se!news.chalmers.se!sunic!EU.net!howland.reston.ans.net!cs.utexas.edu!swrinde!sgiblab!idiom.berkeley.ca.us!apollo.west.oic.com!apollo.west.oic.com!not-for-mail
  2. From: dillon@apollo.west.oic.com (Matthew Dillon)
  3. Newsgroups: comp.sys.amiga.programmer
  4. Subject: Re: How the hell does multitasking work?
  5. Date: 5 May 1994 17:11:42 -0700
  6. Organization: Obvious Implementations Corp
  7. Lines: 151
  8. Distribution: world
  9. Message-ID: <2qc1vu$178@apollo.west.oic.com>
  10. References: <cmanCpBKq0.Lw2@netcom.com>
  11. NNTP-Posting-Host: apollo.west.oic.com
  12.  
  13. In article <cmanCpBKq0.Lw2@netcom.com> cman@netcom.com (Mike Austin) writes:
  14. :I am writing down things that I would want in an operating system and 
  15. :actually making some data structures etc. when I really though about how 
  16. :pre-emptive multi-taking works.  Say you have two processes in a loop 
  17. :with equal priority.  How does exec 'let' on execute it's instructuins 
  18. :for a while then 'let' the other process have some time?  To execute an 
  19. :instruction don't you have to jump to that location?  If you did that you 
  20. :would 'become' that processs and not end until you're done...
  21. :
  22. :Maybe it's more like this (I am NO assembly expert)?
  23. :
  24. :...
  25. :-- 
  26. :                       cout << "cman@netcom.com" << endl;
  27. :
  28. :                  << I get more junk e-mail than junk mail! >>
  29.  
  30.    Well, a lot of people have answered but I figure I'll have a go at it to
  31.    :-)
  32.  
  33.    Basically, a hardware interrupt based on a timer interrupts the currently
  34.    running task after what is known as a time quantum.  For the sake of 
  35.    argument, lets say this quantum is 1 second.
  36.  
  37.    The processor, when it takes the interrupt, pushes the program counter and
  38.    status register onto the stack and jumps to the interrupt handler.  The 
  39.    interrupt handler pushes all remaining registers: D0-D7,A0-A6, and saves
  40.    the user stack pointer (A7 before the interrupt occured) in a known 
  41.    location, usually in a structure which is part of a linked list of
  42.    tasks.
  43.  
  44.    The interrupt handler then accesses the next running task in this linked
  45.    list and loads the stack pointer for the next task.  This stack pointer,
  46.    of course, points to the state information for the second task.  The
  47.    interrupt handler then pops off the registers and does a 
  48.    return-from-interrupt, which restores the status register and program
  49.    counter FOR THE NEXT TASK.  Poof, task #2 is now running.
  50.  
  51.    The next time the interrupt occurs, the interrupt handler repeats the
  52.    work and and on return, Poof, task #1 is running again.  The task's
  53.    do not know or care that they are getting switched back and forth.
  54.  
  55.    Now, back to the time quantum.  If you have two tasks both in an
  56.    infinite loop, with one printing "A" to the screen and the other printing
  57.    "B" to the screen, you would see something like this:
  58.  
  59.        AAAAAAAAAABBBBBBBBBBAAAAAAAAAABBBBBBBBBBAAAAAAAAAABBBBBBBBBB
  60.  
  61.    (this isn't exactly what happens on the amiga since printing requires a
  62.    task switch, but it's a good example)
  63.  
  64.    If you now reduce the time quantum down to, say, 1/10 of a second, you
  65.    would see:
  66.  
  67.        AAABBBAAABBBAAABBBAAABBBAAABBBAAABBBAAABBBAAABBBAAABBBAAABBB
  68.  
  69.    If you now reduce the time quantum down to, say, 1/100 of a second,
  70.    you would see:
  71.  
  72.         ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB
  73.  
  74.    Now, this isn't quite to scale, but you get the idea... the smaller the
  75.    time quantum, the more it 'appears' from the user's perspective that the
  76.    two tasks are running simultaniously.  Of course, there are limits... if
  77.    you make the time quantum too small, the interrupt overhead really slows
  78.    things down.  But anything on the order of 1/30 second will not be 
  79.    noticable in terms of overhead.
  80.  
  81.    --
  82.  
  83.    Now, part #2:  Lets say you have 10 tasks.  You want a way of telling
  84.    the system that any given task is 'sleeping', so the system does not
  85.    switch it in.  If you have 9 sleeping tasks and 1 running task, then
  86.    that 1 running task gets all available CPU until one of the sleeping
  87.    tasks wakes up.
  88.  
  89.    This sleeping/running thing can be implemented through two circular
  90.    queues.  One queue contains a linked list of structures representing
  91.    running tasks, and the other contains a linked list of structures
  92.    representing sleeping tasks.  (Again, not quite the way the Amiga works,
  93.    but good enough for argument).  When a task wants to go to sleep, it
  94.    makes a system call that transfers it's structure form the running queue
  95.    to the waiting queue.  When a task wants to wakeup another task (or
  96.    an interrupt -- say, a serial interrupt to wakeup the terminal program),
  97.    it makes a system call that places the other task back on the run queue.
  98.  
  99.    In this manner, the operating system does not waste time running tasks
  100.    that have nothing to do at the moment.  The task switch interrupt handler
  101.    ONLY deals with the running-tasks-queue.  Most task's are 'waiting' on
  102.    devices.  Some random interrupt causes the device to register an event
  103.    that one or more tasks was waiting for, resulting in the device's
  104.    hardware interrupt routine moving the tasks in question from the wait
  105.    queue to the run queue.
  106.  
  107.    --
  108.  
  109.    part #3:  Priorities.  Lets say you have 10 tasks and they are
  110.    ALL running.  Each task gets about 1/10 of the CPU.  But lets say one
  111.    of those tasks is really important and needs to be able to take more
  112.    CPU.  By implementing a priority scheme you can give that task several
  113.    quantums instead of just one.  In the case of the Amiga, priorities are
  114.    fixed... the Amiga round-robins between all running tasks at the
  115.    highest priority level and any running tasks at a lower priority level
  116.    get no CPU at all.  This works because those higher priority tasks
  117.    do not generally run for very long at a time... they are sleeping most
  118.    of the time.
  119.  
  120.    In something like UNIX, priorities are more dynamic... a higher priority
  121.    process will not completely lockout lower priority processes.
  122.  
  123.    Priorities can be implemented any number of ways... you can adjust the
  124.    time quantum according to the priority, you can simply lock out lower
  125.    priority tasks, or you can use a combination of the two, or do other
  126.    things.
  127.  
  128.    --
  129.  
  130.    part #4:  Preventing screwups.  What happens when two tasks are trying
  131.    to, say, write to the screen?   Lets say you have a common global variable
  132.    which contains the current screen coordinates of the cursor:  x, and y.
  133.    Task #1 read's x and y, stores the character on the screen, increments x,
  134.    and if needs to increments y and scrolls the screen (and zero's x).
  135.  
  136.    The problem is, of course, if two tasks are doing that and the system
  137.    switches between them, the two globals can get corrupted: task #1 reads x,
  138.    system interrupts it and runs task #2 which also reads x (i.e. both
  139.    tasks write to the same cursor position!), not to mention other problems.
  140.  
  141.    To handle this problem, you need some way of 'locking out' the other task
  142.    for the duration of your little write-to-screen operation.  Most operating
  143.    systems provide this in some manner or other... for example, a flag that
  144.    prevents preemptive task switching.  Sophisticated operating systems
  145.    like EXEC and UNIX allow you to selectively lockout different subsystems.
  146.  
  147.    For example, if task #1 is writing to the screen and task #2 is
  148.    writing to the serial port, there is no particular reason to lock them
  149.    out from each other since they both can co-exist without conflict.
  150.  
  151.  
  152.    Well, that's it!
  153.  
  154.                         -Matt
  155.  
  156. -- 
  157.  
  158.     Matthew Dillon        dillon@apollo.west.oic.com
  159.     1005 Apollo Way
  160.     Incline Village, NV. 89451    ham: KC6LVW (no mail drop)
  161.     USA             Sandel-Avery Engineering (702)831-8000
  162.     [always include a portion of the original email in any response!]
  163.